package com.corn.juc.lock;

import lombok.SneakyThrows;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @author : Jim Wu
 * @version 1.0
 * @function :
 * @since : 2020/12/28 16:04
 */

public class LockTimeoutTest {
    public static final Lock lock = new ReentrantLock();

    public static void main(String[] args) throws InterruptedException {
//        testTryLock();
        new Thread() {
            @SneakyThrows
            @Override
            public void run() {
                lock.lockInterruptibly();
                System.out.println(Thread.currentThread().getName() + "\t invoke!");
                TimeUnit.HOURS.sleep(1);
                lock.unlock();
            }
        }.start();

        Thread t2 = new Thread() {
            @Override
            public void run() {
                // 使用lock t2.interrupt无法打断 不会执行 invoke
//                    lock.lock();
                try {
                    lock.lockInterruptibly();
                    // lockInterruptibly 可以被打断 会被InterruptedException捕获进入catch逻辑 最终会打印invoke
                } catch (Exception e) {
                    e.printStackTrace();
                    System.out.println(Thread.currentThread().getName() + "\t interrupted!");
                }
                System.out.println(Thread.currentThread().getName() + "\t invoke!");
//                lock.unlock();
            }
        };
        t2.start();
        t2.interrupt();

    }

    private static void testTryLock() {
        new Thread() {
            @Override
            public void run() {
                try {
                    // 第一次尝试获取锁  tryLock 此时没有线程使用锁 返回true
                    System.out.println(lock.tryLock(3, TimeUnit.SECONDS));
                    System.out.println(Thread.currentThread().getName() + " enter ! ");
                    TimeUnit.HOURS.sleep(1);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    lock.unlock();
                }
            }
        }.start();

        new Thread() {
            @Override
            public void run() {
                try {
                    // 上个线程还没有释放锁 此时尝试获取锁 3秒之后超时 抛出IllegalMonitorStateException try之后代码继续往下执行
                    System.out.println(lock.tryLock(3, TimeUnit.SECONDS));
                    System.out.println(Thread.currentThread().getName() + " enter ! ");
                } catch (Exception e) {
                    e.printStackTrace();
                } finally {
                    lock.unlock();
                }
            }
        }.start();
    }
}
